package com.mmzs.springboot.s00.application.opc;

import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.JIVariant;
import org.openscada.opc.lib.da.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static com.mmzs.springboot.s00.application.opc.BaseConfiguration.*;

public class UtgardCommon {

	public static void main(String[] args) throws Exception {
		final Server server = new Server(BaseConfiguration.getCLSIDConnectionInfomation(),
				Executors.newSingleThreadScheduledExecutor());
		// final String itemId = "通道 1.设备 1.标记 1";MicroWin.NewPLC188.VD950

		// 启动服务
		// final Server server = new Server(ci,
		// Executors.newSingleThreadScheduledExecutor());

		try {
			// 连接到服务
			server.connect();
			// add sync access, poll every 500 ms，启动一个同步的access用来读取地址上的值，线程池每500ms读值一次
			// 这个是用来循环读值的，只读一次值不用这样
			/**
			 * 添加一个Group的信息
			 */
			// OPCGroupStateMgt group = server.addGroup("test", true, 100, 1234, 60,0.0f,
			// 1033);
			Group group = server.addGroup("wuhan");

			final AccessBase access = new SyncAccess(server, 500);
			Thread batchThread = new Thread();
			batchReadData(access, group);

		} catch (final JIException e) {
			System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
		}
	}

	@SuppressWarnings("null")
	private static void batchReadData(final AccessBase access, final Group group) throws Exception {
		// 这是个回调函数,就是读到值后执行这个打印,是用匿名类写的,当然也可以写到外面去
		ArrayList<ArrayList<String>> alldata = new ArrayList<ArrayList<String>>();
		ArrayList<String> needList = new ArrayList<String>();
		for (int i = 0; i < getStringItemIds().length; i++) {
			String itemId = getStringItemIds()[i];
			Boolean flag = false;
			String need_value = useFactorial(access, itemId);
			// Thread.sleep(5000);
			flag = access.isActive();
			while (flag) {
				needList.add(need_value);
			}
		}
		alldata.add(needList); // 添加一行
		WriteDataIntoCsv.Array2CSV(alldata, "test.csv");
		// start reading，开始读值
		access.bind();

		// wait a little bit，有个10秒延时
		Thread.sleep(10000 * 1000);
		// stop reading，停止读取
		access.unbind();
	}

	private static String[] getStringItemIds() {

		String itemIds = getEntryValue(CONFIG_ITEMIDS);
		List<String> itemIds_list = Arrays.asList(itemIds.split(",")).stream().map(s -> s.trim())
				.collect(Collectors.toList());
		String[] need_ids = itemIds_list.toArray(new String[itemIds_list.size()]);
		return need_ids;
	}

	private static String useFactorial(final AccessBase access, String itemId) throws Exception, AddFailedException {
		String result = null;
		boolean flag = false;
		access.addItem(itemId, new DataCallback() {
			@SuppressWarnings("null")
			@Override
			public void changed(Item item, ItemState itemState) {
				int type = 0;
				try {
					System.out.println(itemId + "-----类型值： " + item.read(false).getValue().getType());
				} catch (JIException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				try {
					type = itemState.getValue().getType(); // 类型实际是数字，用常量定义的
				} catch (JIException e) {
					e.printStackTrace();
				}
				System.out.println("监控项的数据类型是：-----" + type);
				System.out.println("监控项的时间戳是：-----" + itemState.getTimestamp().getTime());
				System.out.println("监控项的详细信息是：-----" + itemState);

				// 如果读到是类型的值type=2 对应的西门子word，java类型short
				if (type == JIVariant.VT_I2) {
					short n = 0;
					try {
						n = itemState.getValue().getObjectAsShort();
					} catch (JIException e) {
						e.printStackTrace();
					}
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}
				// 如果读到是类型的值type=3 对应的西门子(DINT)Double Word java类型int
				if (type == JIVariant.VT_I4) {
					Integer n = 0;
					try {
						n = itemState.getValue().getObjectAsInt();
					} catch (JIException e) {
						e.printStackTrace();
					}
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}
				// 如果读到是字符串类型的值type=4,对应西门子的类型是real,java类型float
				if (type == JIVariant.VT_R4) { // 字符串的类型是4
					Float n = null;
					try {
						n = itemState.getValue().getObjectAsFloat();
					} catch (JIException e) {
						e.printStackTrace();
					} // 按字符串读取
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}
				// 如果读到是字符串类型的值type=11,对应西门子的类型是boolean,java类型boolean
				if (type == JIVariant.VT_BOOL) { // 字符串的类型是11
					Boolean n = null;
					try {
						n = itemState.getValue().getObjectAsBoolean();
					} catch (JIException e) {
						e.printStackTrace();
					} // 按字符串读取
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}
				// 如果读到是字符串类型的值type=17,对应西门子的类型是byte,java类型byte
				if (type == JIVariant.VT_UI1) { // 字符串的类型是17
					Number n = null;
					try {
						n = itemState.getValue().getObjectAsUnsigned().getValue();
						System.out.println(
								itemId + " ---------- " + itemState.getValue().getObjectAsUnsigned().getValue());
					} catch (JIException e) {
						e.printStackTrace();
					} // 按字符串读取
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}
				// 如果读到是字符串类型的值type=18,对应西门子的类型是word,java类型short
				if (type == JIVariant.VT_UI2) { // 字符串的类型是18
					Short n = null;
					try {
						n = itemState.getValue().getObjectAsUnsigned().getValue().shortValue();
						System.out.println(itemId + " ---------- "
								+ itemState.getValue().getObjectAsUnsigned().getValue().shortValue());
					} catch (JIException e) {
						e.printStackTrace();
					} // 按字符串读取
//					resultN[0] = ""+n;
					System.out.println(itemId + "-----类型值： " + n);
				}

			}
		});
		flag = access.isActive();
		while (flag) {
			result = "0.9";
		}
		return result;
	}

}